home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d7 / commdrvr.arc / IBMRS232.ASM next >
Assembly Source File  |  1988-04-11  |  25KB  |  679 lines

  1.         page    60,132
  2. ;***********************************************************
  3. ;**                                                       **
  4. ;**  Device Driver for RS232 communications               **
  5. ;**  IBM PC Version                                       **
  6. ;**  Copyright (C) Texas Instruments 1986                 **
  7. ;**  Author: Greg Haley                                   **
  8. ;**                                                       **
  9. ;**  THIS SOURCE CODE MAY BE DISTRIBUTED AND MODIFIED     **
  10. ;**  ONLY IF THE ORIGINAL COPYRIGHT AND AUTHOR CREDITS    **
  11. ;**  REMAIN INTACT.                                       **
  12. ;**                                                       **
  13. ;**  Project Start Date: 11/20/86                         **
  14. ;**                                                       **
  15. ;**  Re: 12/29/86 by Greg Haley                           **
  16. ;**    Added send_xon routine.                            **
  17. ;**    Added 19200 baud.                                  **
  18. ;**                                                       **
  19. ;**  Re: 02/11/87 by Bill Hinkle                          **
  20. ;**    Fixed DLAB baud rate setting bug                   **
  21. ;**                                                       **
  22. ;***********************************************************
  23.  
  24.         name    ibmrs232
  25.         title   Device Driver for IBM PC Communications
  26.  
  27. code    segment byte
  28.    assume cs:code,ds:nothing,es:nothing
  29.  
  30.         include rs232.inc
  31.  
  32.         page
  33. ;***********************************************************
  34. ;**  Keyboard Routines                                    **
  35. ;***********************************************************
  36. keyboard equ    22                      ; IBM PC keyboard INT
  37. altah   db      0                       ; Storage for high byte of key input
  38.  
  39. k_ready:
  40.         mov     al,cs:altah             ; Get 2nd half of F-key?
  41.         or      al,al
  42.         jnz     k_rdy_xit               ; Yes, skip to end
  43.  
  44.         mov     ah,1                    ; Is a char waiting?
  45.         int     keyboard
  46.         jz      k_rdy_xit               ; No, exit
  47.  
  48.         or      ax,ax                   ; If it was a ^C, remove it
  49.         jnz     k_rdy_xit
  50.         xor     ah,ah
  51.         int     keyboard
  52.         jmp     short k_ready           ; And try again
  53.  
  54. k_rdy_xit:
  55.         ret
  56.  
  57. k_read:
  58.         xor     ax,ax                   ; Clear AX
  59.  
  60.         xchg    al,cs:altah             ; Get 2nd half of F-key?
  61.         or      al,al
  62.         jnz     k_r_xit                 ; Yes, skip to end
  63.  
  64. k_r_1:
  65.         xor     ah,ah
  66.         int     keyboard
  67.  
  68.         or      ax,ax                   ; Was it a ^C?
  69.         jz      k_r_1                   ; Yes, get another
  70.  
  71.         or      al,al                   ; Is it a F-key?
  72.         jnz     k_r_xit                 ; No, exit
  73.         mov     cs:altah,ah             ; Yes, save 2nd half
  74.  
  75. k_r_xit:
  76.         ret
  77.  
  78.         page
  79. ;***********************************************************
  80. ;**  Communications Routines                              **
  81. ;***********************************************************
  82. recv_size       equ     800h            ; Receive buffer size
  83.                                         ; Must be one of these values:
  84.                                         ; 0004h = 4 bytes
  85.                                         ; 0008h = 8 bytes
  86.                                         ; 0010h = 16 bytes
  87.                                         ; 0020h = 32 bytes
  88.                                         ; 0040h = 64 bytes
  89.                                         ; 0080h = 128 bytes
  90.                                         ; 0100h = 256 bytes
  91.                                         ; 0200h = 512 bytes
  92.                                         ; 0400h = 1024 bytes
  93.                                         ; 0800h = 2048 bytes
  94.                                         ; 1000h = 4096 bytes
  95.                                         ; 2000h = 8192 bytes
  96.                                         ; 4000h = 16384 bytes
  97.                                         ; 8000h = 32768 bytes
  98. recv_limit      equ     not recv_size   ; Receive buffer limit mask
  99. busy_len        equ     recv_size *3 /4 ; Go busy at 3/4 buf length
  100. not_busy_len    equ     recv_size /2    ; Not busy at 1/2 buf length
  101.  
  102. int_controller  equ     21h             ; 8259A Interrupt Controller port
  103. int_ack         equ     20h             ; 8259A Interrupt Acknowledge port
  104.  
  105. enable_ints     equ     00001111b       ; Enable interrupts
  106. disable_ints    equ     00000000b       ; Disable interrupts
  107. dcd_bit         equ     128             ; DCD bit in modem status register
  108. cts_bit         equ     16              ; CTS bit in modem status register
  109. dsr_bit         equ     32              ; DSR bit in modem status register
  110. ri_bit          equ     64              ; RI bit in modem status register
  111.  
  112. dtr_rts_out2    equ     00001011b       ; DTR, RTS, & OUT2
  113. dlab            equ     10000000b       ; DLAB (Divisor Latch Access Bit)
  114. char_waiting    equ     00000001b       ; Receive buffer full bit
  115. int_pending     equ     00000001b       ; Int pending bit in 8250
  116.  
  117. xon             equ     11h             ; xmit on busy char
  118. xoff            equ     13h             ; xmit off busy char
  119.  
  120.         page
  121. ;***********************************************************
  122. ;**     Variables                                         **
  123. ;***********************************************************
  124.  
  125. old_ss  dw      0                       ; Old SS reg
  126. old_sp  dw      0                       ; Old SP reg
  127.         db      80 dup (?)              ; Stack
  128. i_stack label   byte
  129. rq_head dw      0                       ; Receive Queue start
  130. rq_tail dw      0                       ; Receive Queue stop
  131. rq_len  dw      0                       ; Current receive Queue length
  132. rqueue  db      recv_size dup (?)       ; Receive queue
  133. oldseg  dw      0                       ; Old segment for int vector
  134. oldoff  dw      0                       ; Old offset for int vector
  135. busy_hand       db      0               ; busy handling type
  136. r_busy  db      0                       ; recv busy flag
  137. t_busy  db      0                       ; xmit busy flag
  138. xmit_busy       db      0               ; xmit busy flag (for ints)
  139. m_stat  db      0                       ; Current modem status
  140. l_stat  db      0                       ; Current line status
  141. dcw     dw      1100000001010000b       ; default 2400, 8, N, 1
  142. parity_on       db      0               ; Parity flag
  143.  
  144. int_tbl dw      mod_stat                ; Interrupt branch table
  145.         dw      xmit_mt
  146.         dw      rec_full
  147.         dw      lin_stat
  148.  
  149. ; table for baud rate constants
  150. baud_tbl        dw      417h            ; 110
  151.                 dw      300h            ; 150
  152.                 dw      180h            ; 300
  153.                 dw      0c0h            ; 600
  154.                 dw      60h             ; 1200
  155.                 dw      30h             ; 2400
  156.                 dw      18h             ; 4800
  157.                 dw      0ch             ; 9600
  158.  
  159. speed   dw      0030h                   ; Baud rate to use (2400)
  160. comm_parms      db      00000011b       ; No parity, 8 data, 1 stop
  161.  
  162. ; table for port number init tables
  163. p_table dw      port1_tbl
  164.         dw      port2_tbl
  165.  
  166. port_n  dw      port1_tbl               ; default port is 1
  167.  
  168. ; port 1 init table
  169. port1_tbl       dw      0ch             ; Interrupt vector for irq
  170.                 db      11101111b       ; Mask to enable irq
  171.                 db      00010000b       ; Mask to unable irq
  172.                 dw      3f8h            ; Receive buffer port
  173.                 dw      3f8h            ; Transmit buffer port
  174.                 dw      3f8h            ; Divisor least significant byte
  175.                 dw      3f9h            ; Divisor most significant byte
  176.                 dw      3fbh            ;  8250 UART Control port
  177.                 dw      3fdh            ;  8250 UART Status port
  178.                 dw      3fch            ;  8250 Modem Control port
  179.                 dw      3feh            ;  8250 Modem Status port
  180.                 dw      3f9h            ;  8250 interrupt enable register
  181.                 dw      3fah            ;  8250 interrupt ack register
  182.                 db      64h             ;  8259 Specific EOI
  183. p_tbl_size      equ     $-port1_tbl
  184.  
  185. ; port 2 init table
  186. port2_tbl       dw      0bh             ; Interrupt vector for irq
  187.                 db      11110111b       ; Mask to enable irq
  188.                 db      00001000b       ; Mask to unable irq
  189.                 dw      2f8h            ; Receive buffer port
  190.                 dw      2f8h            ; Transmit buffer port
  191.                 dw      2f8h            ; Divisor least significant byte
  192.                 dw      2f9h            ; Divisor most significant byte
  193.                 dw      2fbh            ;  8250 UART Control port
  194.                 dw      2fdh            ;  8250 UART Status port
  195.                 dw      2fch            ;  8250 Modem Control port
  196.                 dw      2feh            ;  8250 Modem Status port
  197.                 dw      2f9h            ;  8250 interrupt enable register
  198.                 dw      2fah            ;  8250 interrupt ack register
  199.                 db      63h             ;  8259 Specific EOI
  200.  
  201. ; defaults for port 1
  202. port_tbl        label   word
  203. comm1_vector    dw      0ch             ; Interrupt vector for irq
  204. irq_enab_mask   db      11101111b       ; Mask to enable irq
  205. irq_unab_mask   db      00010000b       ; Mask to unable irq
  206. recv_buffer     dw      3f8h            ; Receive buffer port
  207. send_buffer     dw      3f8h            ; Transmit buffer port
  208. lsb_divisor     dw      3f8h            ; Divisor least significant byte
  209. msb_divisor     dw      3f9h            ; Divisor most significant byte
  210. line_control    dw      3fbh            ;  8250 UART Control port
  211. line_status     dw      3fdh            ;  8250 UART Status port
  212. modem_control   dw      3fch            ;  8250 Modem Control port
  213. modem_status    dw      3feh            ;  8250 Modem Status port
  214. int_enable      dw      3f9h            ;  8250 interrupt enable register
  215. int_id          dw      3fah            ;  8250 interrupt ID register
  216. SEOI            db      64h             ;  8259 Specific EOI
  217.  
  218.         page
  219. ;***********************************************************
  220. ;**     Subroutine to set up comm chip per the DCW        **
  221. ;**     DCW is in AX                                      **
  222. ;***********************************************************
  223. set_dcw:
  224.  
  225. ; clear comm parms
  226.         xor     dl,dl
  227.  
  228. ; set parity type
  229.         mov     bl,al                   ; get low byte in BL
  230.         and     bl,00000011b            ; mask unused bits
  231.         or      dl,bl                   ; change parity
  232.         mov     cl,3
  233.         shl     dl,cl
  234.         and     bl,00000001b            ; change parity flag
  235.         mov     parity_on,bl            ;
  236.  
  237. ; set num stop bits
  238.         mov     bl,al                   ; get low byte in BL
  239.         and     bl,00001000b            ; mask unused bits
  240.         shr     bl,1
  241.         or      dl,bl
  242.  
  243. ; set data bits
  244.         mov     bl,ah                   ; get high byte in BL
  245.         and     bl,01000000b            ; mask unused bits
  246.         or      bl,10000000b
  247.         mov     cl,6
  248.         shr     bl,cl
  249.         or      dl,bl
  250.  
  251. ; Save comm parms
  252.         mov     comm_parms,dl
  253.  
  254. ; set baud rate
  255.         mov     bl,al                   ; get low byte in BL
  256.         and     bl,11110000b            ; mask unused bits
  257.         mov     cl,3                    ; shift to make word ptr
  258.         shr     bl,cl
  259.         mov     si,offset baud_tbl      ; point to baud table
  260.         xor     bh,bh                   ; make BX a byte ptr
  261.         add     si,bx                   ; SI now points to baud rate const
  262.         mov     dx,word ptr [si]        ; get baud rate in DX
  263.         mov     speed,dx                ; save baud rate
  264.  
  265. ; set busy type
  266.         mov     bl,ah
  267.         and     bl,00000011b            ; mask unwanted bits
  268.         mov     byte ptr busy_hand,bl   ; store it
  269.  
  270. ; set port number
  271.         mov     bl,ah                   ; get high byte in BL
  272.         and     bl,00001000b            ; mask unused bits
  273.         shr     bl,1                    ; shift to make word ptr
  274.         shr     bl,1
  275.         mov     si,offset p_table       ; point to port table
  276.         xor     bh,bh                   ; make BX a byte ptr
  277.         add     si,bx                   ; SI now points to baud rate const
  278.         mov     dx,word ptr [si]        ; get port adrs in DX
  279.         mov     word ptr port_n,dx      ; save port number adrs
  280.         ret
  281.  
  282.         page
  283. ;***********************************************************
  284. ;**     Subroutine to set up interrupt vector             **
  285. ;**     and initialize the  8250 comm chip                **
  286. ;***********************************************************
  287. init_comm:
  288.         push    ds
  289.         push    cs
  290.         pop     ds
  291.  
  292. ; get correct port parameters
  293.         push    es
  294.         push    cs
  295.         pop     es
  296.  
  297.         mov     si,word ptr port_n      ; get port table adrs
  298.         mov     di,offset port_tbl      ; DI points to table to use
  299.         mov     cx,p_tbl_size           ; CX has table length
  300.         repz    movsb                   ; move it
  301.  
  302.         pop     es
  303.  
  304. ; Save old int vector for irq
  305.         mov     di,comm1_vector
  306.         call    get_vector
  307.         mov     word ptr oldseg,bx
  308.         mov     word ptr oldoff,dx
  309.  
  310. ; Set up int vector for irq
  311.         push    cs                      ; Make BX = CS
  312.         pop     bx
  313.         mov     dx,offset isr
  314.         mov     di,comm1_vector
  315.         call    set_vector
  316.  
  317. ; Enable irq from 8259A
  318.         cli
  319.         in      al,int_controller
  320.         jmp     $+2                     ; delay
  321.         and     al,irq_enab_mask
  322.         out     int_controller,al
  323.  
  324. ; Set baud rate, parity, etc.
  325.         mov     dx,line_control
  326.         mov     al,comm_parms
  327.         or      al,dlab                 ; Bring up DLAB
  328.         out     dx,al
  329.         mov     dx,lsb_divisor          ; Set LSB of Divisor Latch
  330.         mov     ax,speed
  331.         out     dx,al
  332.         mov     dx,msb_divisor          ; Set MSB of Divisor Latch
  333.         mov     al,ah
  334.         out     dx,al
  335.         mov     dx,line_control
  336.         in      al,dx
  337.         and     al,not dlab
  338.         out     dx,al
  339.  
  340. ; Read receive buffer register
  341.         call    lin_stat
  342.         test    al,char_waiting
  343.         jz      init_1
  344.         mov     dx,recv_buffer
  345.         in      al,dx
  346. init_1:
  347.  
  348. ; Read modem control register
  349.         mov     dx,modem_control
  350.         in      al,dx
  351.  
  352. ; Read modem status register
  353.         call    mod_stat
  354.  
  355. ; Read UART status register
  356.         call    lin_stat
  357.  
  358. ; Enable 8250 interrupts
  359.         mov     dx,line_control
  360.         in      al,dx
  361.         and     al,not dlab
  362.         out     dx,al
  363.         mov     dx,int_enable
  364.         mov     al,enable_ints
  365.         out     dx,al
  366.  
  367. ; Raise DTR, RTS, & OUT2
  368.         mov     dx,modem_control
  369.         mov     al,dtr_rts_out2
  370.         out     dx,al
  371.  
  372.         pop     ds
  373.         sti
  374.         ret
  375.  
  376.         page
  377. ;***********************************************************
  378. ;**     Subroutine to restore interrupt vector            **
  379. ;**     and reset the  8250 comm chip                     **
  380. ;***********************************************************
  381. de_init:
  382.         cli
  383.  
  384. ; Disable irq
  385.         in      al,int_controller
  386.         or      al,cs:byte ptr irq_unab_mask
  387.         jmp     $+2                     ; delay
  388.         jmp     $+2                     ; delay
  389.         out     int_controller,al
  390.  
  391. ; Disable interrupts on  8250 and drop DTR, RTS
  392.         mov     dx,cs:line_control
  393.         in      al,dx
  394.         jmp     $+2                     ; delay
  395.         and     al,not dlab
  396.         out     dx,al
  397.         mov     dx,cs:int_enable
  398.         xor     al,al
  399.         out     dx,al
  400.  
  401. ; It's probably not a good idea to restore the vector at close in
  402. ; this case, but here's the code to do it:
  403. ;
  404. ; Restore int vector for irq
  405. ;       mov     bx,cs:word ptr oldseg
  406. ;       mov     dx,cs:word ptr oldoff
  407. ;       mov     di,comm1_vector
  408. ;       call    set_vector
  409.         sti
  410.         ret
  411.  
  412.         page
  413. ;***********************************************************
  414. ;**     Interrupt Service Routine                         **
  415. ;***********************************************************
  416. isr:
  417.         cli
  418.         cld
  419. ; Set up new stack
  420.         mov     cs:word ptr old_sp,sp
  421.         mov     cs:word ptr old_ss,ss
  422.         mov     sp,cs
  423.         mov     ss,sp
  424.         mov     sp,offset i_stack
  425.  
  426.         push    ax
  427.         push    bx
  428.         push    cx
  429.         push    dx
  430.         push    ds
  431.  
  432.         push    cs
  433.         pop     ds
  434.  
  435. ; Verify int came from  8250
  436.         mov     dx,int_id
  437.         in      al,dx
  438.         test    al,int_pending
  439.         jnz     isr_exit
  440.  
  441. ; Branch to correct routine
  442.         cbw                             ; make int type a word
  443.         mov     bx,offset int_tbl       ; point to int table
  444.         add     bx,ax                   ; add int type
  445.         sti
  446.         call    cs:word ptr [bx]        ; go do subroutine
  447.         cli
  448.  
  449. isr_exit:
  450. ; Tell 8259A we're done
  451.         mov     al,SEOI
  452.         out     int_ack,al
  453.  
  454.         pop     ds
  455.         pop     dx
  456.         pop     cx
  457.         pop     bx
  458.         pop     ax
  459.  
  460. ; restore stack
  461.         mov     ss,cs:word ptr old_ss
  462.         mov     sp,cs:word ptr old_sp
  463.  
  464.         sti
  465.         iret
  466.  
  467.         page
  468. ;***********************************************************
  469. ;**     Subroutine to read the modem status               **
  470. ;***********************************************************
  471. mod_stat:
  472.         mov     dx,modem_status         ; Read modem status (CHB)
  473.         in      al,dx                   ;   into reg AL
  474.  
  475.         xor     ah,ah
  476.         test    al,ri_bit
  477.         jz      test_dsr
  478.         or      ah,4
  479. test_dsr:
  480.         test    al,dsr_bit
  481.         jz      test_cts
  482.         or      ah,1
  483. test_cts:
  484.         shl     ah,1
  485.         test    al,cts_bit
  486.         jz      test_dcd
  487.         or      ah,1
  488. test_dcd:
  489.         shl     ah,1
  490.         test    al,dcd_bit
  491.         jz      test_done
  492.         or      ah,1
  493. test_done:
  494.  
  495. ; AH now contains the line signals
  496. ; ---------------------------------
  497. ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
  498. ; ---------------------------------
  499. ; |   |   |   | RI|   |DSR|CTS|DCD|
  500. ; ---------------------------------
  501. ; 0=down, 1=up
  502.  
  503.         mov     cs:byte ptr m_stat,ah   ; Update current modem status
  504.  
  505. ; Check for busy handling
  506.         shr     ah,1                    ; DSR in bit 0
  507.         shr     ah,1
  508.         cmp     cs:byte ptr busy_hand,2 ; DSR busy handling?
  509.         jne     xit_mod_stat            ;  No, skip
  510.         mov     al,ah                   ; save AH
  511. set_tbusy:
  512.         and     al,1                    ; up = busy on
  513. ;       not     al                      ; down = busy on
  514.         mov     cs:byte ptr t_busy,al   ; set busy
  515.  
  516.  
  517. xit_mod_stat:
  518.         ret
  519.  
  520.         page
  521. ;***********************************************************
  522. ;**     Subroutine to send the next char in queue         **
  523. ;***********************************************************
  524. xmit_mt:
  525.         mov     cs:byte ptr xmit_busy,0 ; We're not busy
  526.  
  527.         ret
  528.  
  529.         page
  530. ;***********************************************************
  531. ;**     Subroutine to receive a char and queue it         **
  532. ;***********************************************************
  533. rec_full:
  534.         mov     dx,recv_buffer          ; Get char
  535.         in      al,dx
  536.         cmp     cs:byte ptr parity_on,0 ; parity?
  537.         jz      no_par                  ;   No, don't mask off parity bit
  538.         and     al,7fh                  ;   Yes, mask off parity bit
  539. no_par:
  540. ; check for XON-XOFF busy char
  541.         cmp     cs:byte ptr busy_hand,3 ; XON-XOFF busy handling?
  542.         jne     queue_char              ;  No, skip busy handling
  543.         cmp     al,xoff                 ; Need to set busy?
  544.         jne     chk_r_xon               ;  No, skip
  545.         mov     cs:byte ptr t_busy,1    ; set busy
  546.         jmp     xit_rec_full            ; We're done
  547.  
  548. chk_r_xon:
  549.         cmp     al,xon                  ; Need to reset busy?
  550.         jne     queue_char              ;  No, skip busy handling
  551.         mov     cs:byte ptr t_busy,0    ; reset busy
  552.         jmp     xit_rec_full            ; We're done
  553.  
  554. queue_char:
  555. ; check for buffer overflow
  556.         cmp     cs:word ptr rq_len,recv_limit ; buffer full?
  557.         jb      buf_full1               ; No, skip
  558.         inc     cs:word ptr rq_tail     ; Yes, lose 1 char
  559.         and     cs:word ptr rq_tail,recv_limit
  560.         dec     cs:word ptr rq_len      ; Adjust queue length
  561. buf_full1:
  562.  
  563.         mov     bx,offset rqueue        ; Queue char
  564.         mov     dx,cs:word ptr rq_head
  565.         add     bx,dx
  566.         mov     cs:byte ptr [bx],al
  567.         inc     dx
  568.         and     dx,recv_limit           ; wrap if >= receive size
  569.         mov     cs:word ptr rq_head,dx
  570.         inc     cs:word ptr rq_len      ; Adjust queue length
  571.  
  572. ; set busy if needed
  573.         cmp     cs:byte ptr busy_hand,3 ; XON-XOFF busy handling?
  574.         jne     set_rb_done             ; No, skip
  575.         cmp     cs:word ptr rq_len,busy_len ; Need to set busy?
  576.         jb      set_rb_done             ; No, skip
  577.         mov     cs:byte ptr r_busy,1    ; set busy flag
  578.         mov     dx,cs:word ptr send_buffer ; send XOFF char
  579.         mov     al,xoff
  580.         out     dx,al
  581. set_rb_done:
  582.  
  583. xit_rec_full:
  584.         ret
  585.  
  586.         page
  587. ;***********************************************************
  588. ;**     Subroutine to send an xon char if needed          **
  589. ;***********************************************************
  590. send_xon:
  591.         cmp     cs:byte ptr busy_hand,3 ; XON-XOFF busy handling?
  592.         jne     xit_send_xon            ; No, skip
  593.         mov     dx,cs:word ptr send_buffer ; send XOFF char
  594.         mov     al,xon
  595.         out     dx,al
  596.  
  597. xit_send_xon:
  598.         ret
  599.  
  600.         page
  601. ;***********************************************************
  602. ;**     Subroutine to read the line status                **
  603. ;***********************************************************
  604. lin_stat:
  605.         mov     dx,line_status
  606.         in      al,dx                   ; read status
  607.         mov     cs:byte ptr l_stat,al   ; Update current line status
  608.  
  609.         ret
  610.  
  611.         page
  612. ;***********************************************************
  613. ;**     Subroutine to get an interrupt vector             **
  614. ;**                                                       **
  615. ;**   di = vector number                                  **
  616. ;**                                                       **
  617. ;**   Return:                                             **
  618. ;**   bx = segment                                        **
  619. ;**   dx = offset                                         **
  620. ;***********************************************************
  621. get_vector:
  622.         push    es
  623.         xor     ax,ax
  624.         mov     es,ax
  625.         shl     di,1
  626.         shl     di,1
  627.         mov     dx,es:word ptr[di]
  628.         mov     bx,es:word ptr[di+2]
  629.         pop     es
  630.         ret
  631.  
  632.         page
  633. ;***********************************************************
  634. ;**     Subroutine to set an interrupt vector             **
  635. ;**                                                       **
  636. ;**   di = vector number                                  **
  637. ;**   bx = segment                                        **
  638. ;**   dx = offset                                         **
  639. ;***********************************************************
  640. set_vector:
  641.         push    es
  642.         xor     ax,ax
  643.         mov     es,ax
  644.         shl     di,1
  645.         shl     di,1
  646.         mov     es:word ptr[di],dx
  647.         mov     es:word ptr[di+2],bx
  648.         pop     es
  649.         ret
  650.  
  651.         page
  652. ;***********************************************************
  653. ;**  Everything past here is truncated after install      **
  654. ;***********************************************************
  655.  
  656. init    proc    near
  657.         lds     bx,cs:[ptrsav]
  658.         mov     word ptr [bx].trans,offset init ;set break address
  659.         mov     [bx].trans+2,cs
  660.  
  661.         push    cs
  662.         pop     ds
  663.         mov     dx,offset init_msg
  664.         mov     ah,9
  665.         int     21h
  666.  
  667.         jmp     exit
  668. init    endp
  669.  
  670. init_msg:
  671.         db      cr,lf,'IBM PC Communications Driver v2.52'
  672.         db      ' Copyright (C) Texas Instruments 1986, 1987'
  673.         db      cr,lf,'Written by '
  674.         db      'Greg Haley',cr,lf
  675.         db      'Modified 02-12-87 by Bill Hinkle'
  676.         db      cr,lf,cr,lf,'$'
  677. code    ends
  678.         end
  679.